cmake_minimum_required(VERSION 3.14.0)

include_guard(GLOBAL)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# set(CMAKE_VERBOSE_MAKEFILE ON)

function(declare_component NS PROJ PROJ_DIR)
  set(NS ${NS} PARENT_SCOPE)
  set(PROJ ${PROJ} PARENT_SCOPE)
  set(PROJ_DIR__${NS}__${PROJ} "${PROJ_DIR}" PARENT_SCOPE)
  unset(COMPONENT_DEPS__${NS}__${PROJ} PARENT_SCOPE)
  list(APPEND COMPONENT_LIST ${NS}__${PROJ})
  set(COMPONENT_LIST ${COMPONENT_LIST} PARENT_SCOPE)
endfunction()

function(require_component COMP_NS COMP_PROJ)
  list(APPEND COMPONENT_DEPS__${NS}__${PROJ} ${COMP_NS}__${COMP_PROJ})
  set(COMPONENT_DEPS__${NS}__${PROJ} ${COMPONENT_DEPS__${NS}__${PROJ}} PARENT_SCOPE)
endfunction()

function(_expand_components COMPONENTS)
  foreach(COMPONENT ${${COMPONENTS}})
    if(COMPONENT_DEPS__${COMPONENT})
      _expand_components(COMPONENT_DEPS__${COMPONENT})
    endif()
    list(APPEND EXPAND_LIST ${COMPONENT})
    set(EXPAND_LIST ${EXPAND_LIST} PARENT_SCOPE)
  endforeach()
endfunction()

function(build_all_components)
  unset(EXPAND_LIST)
  _expand_components(COMPONENT_LIST)
  foreach(COMPONENT ${EXPAND_LIST})
    if(ADDED_FLAG_${COMPONENT})
      continue()
    endif()
    message("> Add component ${COMPONENT}")
    add_subdirectory(${CMAKE_SOURCE_DIR}/${PROJ_DIR__${COMPONENT}})
    set(ADDED_FLAG_${COMPONENT} 1)
  endforeach()
endfunction()

function(bgn_component NS PROJ)
  set(NS ${NS} PARENT_SCOPE)
  set(PROJ ${PROJ} PARENT_SCOPE)
endfunction()

function(end_component)
  foreach(COMPONENT ${COMPONENT_DEPS__${NS}__${PROJ}})
    if (TARGET ${NS}__${PROJ}__cc_lib AND TARGET ${COMPONENT}__cc_lib)
      if (${NS}__${PROJ}__cc_lib__is_interface)
        target_link_libraries(${NS}__${PROJ}__cc_lib INTERFACE ${COMPONENT}__cc_lib)
      else()
        target_link_libraries(${NS}__${PROJ}__cc_lib PUBLIC ${COMPONENT}__cc_lib)
      endif()
    endif()
  endforeach()
endfunction(end_component)
